package com.aijk.commons.register;

import com.aijk.conifg.PublicConfig;
import com.aijk.commons.utils.IpUtils;
import org.I0Itec.zkclient.ZkClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.CreateMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>将当前节点注册到ZK，注册后获得节点序号，节点序号与IP绑定</p>
 * User: chendw
 * Date: 2016/8/19 16:05
 * To change this template use File | Settings | File Templates.
 */
public enum ClusterHostUtils {

    INSTANCE;

    private final Logger logger = LoggerFactory.getLogger(ClusterHostUtils.class);

    private static long nodeId;

    private ZkClient zkClient;
    /**
     * 存储节点序号的ZK目录
     */
    private static final String ROOT_PATH = "/eh/host";

    /**
     * 存储全局当前分配的最大序号
     */
    private static final String NODE_PATH = ROOT_PATH + "/node";

    /**
     * 存储IP对应序号目录
     */
    private static final String HOST_SEQ_PATH = ROOT_PATH + "/address";

    /**
     * 注册节点并返回主机信息
     *
     * @return
     */
    public HostInfo registerHost() {
        if (zkClient == null) {
            zkClient = new ZkClient(PublicConfig.REGISTER_CENTER);
        }

        // 初始化PATH
        checkRootPath();

        String hostAddress = IpUtils.getRealIp();

        // 判断节点是否已注册
        String hostNode = NODE_PATH + "/" + hostAddress;

        HostInfo hostInfo;
        if (!zkClient.exists(hostNode)) { // 注册节点
            hostInfo = new HostInfo();

            String result = zkClient.create(HOST_SEQ_PATH + "/" + hostAddress, hostAddress, CreateMode.PERSISTENT_SEQUENTIAL);
            logger.info("创建序号节点 : {}", result);

            long nodeId = Long.parseLong(StringUtils.right(result, 10));
            logger.info("获得节点编号 : {}", nodeId);

            hostInfo.setId(nodeId);
            String seqNode = zkClient.create(hostNode, hostInfo, CreateMode.PERSISTENT);
            logger.info("创建主机节点 : {}", seqNode);

        } else { // 读取节点
            hostInfo = zkClient.readData(hostNode);
            logger.info("获得节点编号 : {}", hostInfo.getId());
        }
        return hostInfo;
    }

    private void checkRootPath() {
        if (!zkClient.exists(ROOT_PATH)) {
            zkClient.create(ROOT_PATH, null, CreateMode.PERSISTENT);
            logger.info("创建 ZK HOST 目录 : {}", ROOT_PATH);
        }

        if (!zkClient.exists(NODE_PATH)) {
            zkClient.create(NODE_PATH, null, CreateMode.PERSISTENT);
            logger.info("创建 ZK NODE 键值 : {}", NODE_PATH);
        }

        if (!zkClient.exists(HOST_SEQ_PATH)) {
            zkClient.create(HOST_SEQ_PATH, null, CreateMode.PERSISTENT);
            logger.info("创建 ZK HOST ADDRESS 键值 : {}", NODE_PATH);
        }
    }
}
